package com.itheima.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.constant.MessageConstant;
import com.itheima.dao.MenuDao;
import com.itheima.dao.RoleDao;
import com.itheima.dao.UserDao;
import com.itheima.entity.PageResult;
import com.itheima.pojo.Menu;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 角色服务接口实现类
 *
 * @author wangxin
 * @version 1.0
 */
@Service(interfaceClass = RoleService.class)
@Transactional
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleDao roleDao;
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private JedisPool jedisPool;
    @Autowired
    private UserDao userDao;

    /**
     * 1.*角色分页查询
     */
    @Override
    public PageResult findPage(Integer currentPage, Integer pageSize, String queryString) {
        PageHelper.startPage(currentPage, pageSize);
        //2.需要分页的语句
        Page<Role> checkGroupPage = roleDao.selectByCondition(queryString);
        return new PageResult(checkGroupPage.getTotal(), checkGroupPage.getResult());
    }

    /**
     * 2.*添加角色
     */
    @Override
    public void add(Role role, Integer[] permissionIds, Integer[] menuIds) {
        // 需要校验角色名称是否已经存在
        // 需要校验角色关键字是否已经存在
        List<Role> roleList = roleDao.findAll();
        if (roleList != null && roleList.size() > 0) {
            for (Role dbRole : roleList) {
                // 名字全部转换成小写
                if (dbRole.getName().toLowerCase().equals(role.getName().toLowerCase())) {
                    throw new RuntimeException(MessageConstant.SET_ROLE_NAME_FAIL);
                }
                // 关键字全部转换成大写
                if (dbRole.getKeyword().toUpperCase().equals(role.getKeyword().toUpperCase())) {
                    throw new RuntimeException(MessageConstant.SET_ROLE_KEYWORD_FAIL);
                }
            }
        }
        // 往角色表添加
        roleDao.add(role);
        // 往角色表与权限表中间写记录
        setRoleAndPermission(role.getId(), permissionIds);
        // 往角色表与菜单表中间写记录
        setRoleAndMenu(role.getId(), menuIds);
    }

    /**
     * 2.2.*往角色表与权限表中间写记录
     */
    public void setRoleAndPermission(Integer roleId, Integer[] permissionIds) {
        if (permissionIds != null && permissionIds.length > 0) {
            for (Integer permissionId : permissionIds) {
                Map<String, Integer> map = new HashMap<>();
                map.put("roleId", roleId);
                map.put("permissionId", permissionId);
                // 在t_role_permission添加记录
                roleDao.setRoleAndPermission(map);
            }
        }
    }

    /**
     * 2.3.*往角色表与菜单表中间写记录
     */
    private void setRoleAndMenu(Integer roleId, Integer[] menuIds) {
        if (menuIds != null && menuIds.length > 0) {
            for (Integer menuId : menuIds) {
                Map<String, Integer> map = new HashMap<>();
                map.put("roleId", roleId);
                map.put("menuId", menuId);
                // 在t_role_menu添加记录
                roleDao.setRoleAndMenu(map);
            }
        }
    }

    /**
     * 2.1*添加角色时查询所有权限
     */
    @Override
    public List<Permission> findAllPermission() {
        return roleDao.findAllPermission();
    }

    /**
     * 2.1*添加角色时查询所有菜单
     */
    @Override
    public List<Menu> findAllMenu() {
        return roleDao.findAllMenu();
    }


    /**
     * 3.1*编辑角色-回显角色
     */
    @Override
    public Role findById(Integer roleId) {
        return roleDao.findById(roleId);
    }

    /**
     * 3.2*编辑角色-回显权限ids
     */
    @Override
    public List<Integer> findPermissionIdsByRoleId(Integer roleId) {
        return roleDao.findPermissionIdsByRoleId(roleId);
    }

    /**
     * 3.3*编辑角色-回显菜单ids
     */
    @Override
    public List<Integer> findMenuIdsByRoleId(Integer roleId) {
        return roleDao.findMenuIdsByRoleId(roleId);
    }

    /**
     * 3.4*编辑角色-提交角色信息
     */
    @Override
    public void edit(Role role, Integer[] permissionIds, Integer[] menuIds) {
        // 需要校验角色名称是否已经存在
        // 需要校验角色关键字是否已经存在
        List<Role> roleList = roleDao.findAll();
        if (roleList != null && roleList.size() > 0) {
            for (Role dbRole : roleList) {
                // 如果循环的角色和当前角色是同一个不管.不是同一个则要判断
                if(!role.getId().equals(dbRole.getId())) {
                    // 名字全部转换成小写
                    if (dbRole.getName().toLowerCase().equals(role.getName().toLowerCase())) {
                        throw new RuntimeException(MessageConstant.SET_ROLE_NAME_FAIL);
                    }
                    // 关键字全部转换成大写
                    if (dbRole.getKeyword().toUpperCase().equals(role.getKeyword().toUpperCase())) {
                        throw new RuntimeException(MessageConstant.SET_ROLE_KEYWORD_FAIL);
                    }
                }
            }
        }
        // 更新角色表 update
        roleDao.updateRole(role);

        // 先删除角色表与权限表记录(中间表)
        roleDao.deleteAssociationRoleAndPermission(role.getId());
        // 重新建立角色表与权限表关系(中间表)
        setRoleAndPermission(role.getId(), permissionIds);

        // 先删除角色表与菜单表记录(中间表)
        roleDao.deleteAssociationRoleAndMenu(role.getId());
        // 重新建立角色表与菜单表关系(中间表)
        setRoleAndMenu(role.getId(), menuIds);

        // TODO
        // 更新角色关联的用户的菜单列表
        // 查询该角色关联的用户列表
        List<String> usernames = userDao.findUsernamesByRole(role);
        Jedis jedis = jedisPool.getResource();
        if (usernames != null && usernames.size() > 0) {
            for (String username : usernames) {
                // 从redis拿当前用户名对应的key的值.
                String menuListStr = jedis.get("MENU_LIST_" + username);
                // 如果不为空则更新一下redis
                if (menuListStr != null) {
                    List<Menu> menuList = menuDao.queryParentMenu(username);
                    // 根据父菜单和username再查询其子菜单
                    Map<String, Object> map = new HashMap<>();
                    if (menuList != null && menuList.size() > 0) {
                        for (Menu menu : menuList) {
                            map.put("parentId", menu.getId());
                            map.put("username", username);
                            List<Menu> childrenList = menuDao.queryChildrenMenu(map);
                            menu.setChildren(childrenList);
                        }
                    }
                    // 存入redis中
                    jedis.set("MENU_LIST_" + username, JSON.toJSONString(menuList));
                }
            }
        }
    }

    /**
     * 4.*删除角色
     */
    @Override
    public void deleteById(Integer roleId) {
        // 4.1使用角色id，查询角色和权限中间表
        Integer count1 = roleDao.findRoleAndPermissionCountByRoleId(roleId);
        // 存在数据
        if (count1 > 0) {
            throw new RuntimeException("当前角色和权限之间存在关联关系，不能删除");
        }
        // 4.2使用角色id，查询角色和菜单中间表
        Integer count2 = roleDao.findRoleAndMenuCountByRoleId(roleId);
        // 存在数据
        if (count2 > 0) {
            throw new RuntimeException("当前角色和菜单之间存在关联关系，不能删除");
        }
        // 4.3删除角色
        roleDao.deleteById(roleId);
    }
}
